<!DOCTYPE html>
<html lang="zh-CN">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  
  
  <!-- 关键字 keywords -->
  
  <meta name="keywords" content="juc,future,天赐,天赐の小站,博客">
  
  
  <title itemprop="name">JUC学习笔记-异步编程：Future与Callable | 天赐の小站</title>
  
    <link rel="shortcut icon" href="//fastly.jsdelivr.net/gh/tiancixiong/cdn@v1.0/img/custom/favicon.ico">
  
  <meta http-equiv="x-dns-prefetch-control" content="on">
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Noto+SerifMerriweather|Merriweather+Sans|Source+Code+Pro|Ubuntu:400,700|Noto+Serif+SC" media="all">
  <link rel="dns-prefetch" href="//cdn.jsdelivr.net">
  <link rel="stylesheet" id="saukra_css-css" href="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/css/style.css" type="text/css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/css/lib.min.css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/css/font.css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/css/insight.css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/css/jquery.fancybox.min.css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/css/zoom.css" media="all">
  <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/css/sharejs.css">
<!--   <link rel="stylesheet" id="saukra_css-css" href="https://2heng.xin/wp-content/cache/autoptimize/css/autoptimize_ad42a61f4c7d4bdd9f91afcff6b5dda5.css
" type="text/css" media="all"> -->
  <script>
  /*Initial Variables*/
  var mashiro_option = new Object();
  var mashiro_global = new Object();
  mashiro_option.NProgressON = true;
  /* 
   * 邮箱信息之类的东西可以填在这里，这些js变量基本都作用于sakura-app.js
   * 这样的设置仅是为了方便在基于PHP开发的主题中设置js变量，既然移植到了Node上，我想或许可以精简这一逻辑吧
   */
  mashiro_option.email_domain = "";
  mashiro_option.email_name = "";
  mashiro_option.cookie_version_control = "";
  mashiro_option.qzone_autocomplete = false;
  mashiro_option.site_name = "天赐の小站";
  mashiro_option.author_name = "天赐の小站";
  mashiro_option.site_url = "/";
  mashiro_option.v_appId = "VeenC2gYYyfSOq2rcCSmmruy-MdYXbMMI";
  mashiro_option.v_appKey = "F5kjyHdh4akqc7SDmfzQP8Qi";
  mashiro_option.v_notify = false;
  mashiro_option.v_verify = false;
  mashiro_option.v_placeholder = "你是我一生只会遇见一次的惊喜 ...";
  mashiro_option.v_avatar = "monsterid";
  mashiro_option.v_pageSize = "5" || 10;
  mashiro_option.mathjax = "0";
  mashiro_option.qq_api_url = "https://api.mashiro.top/qqinfo/"; 
  mashiro_option.qq_avatar_api_url = "https://api.mashiro.top/qqinfo/";

  // mashiro_option.jsdelivr_css_src = "https://cdn.jsdelivr.net/gh/moezx/cdn@3.4.5/css/lib.min.css";
  // mashiro_option.float_player_on = true;
  console.info("%c Blog %c", "background:#24272A; color:#ffffff", "", "https://blog.xiongtianci.com");
  console.info("%c GitHub %c", "background:#24272A; color:#ffffff", "", "https://github.com/tiancixiong");
  /*End of Initial Variables*/
  </script>
  <script type="text/javascript">
  var bg = "https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/5cm_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/5cm_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/A.Voyage.of.Chihiro_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/A.Voyage.of.Chihiro_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/A.Voyage.of.Chihiro_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/A.Voyage.of.Chihiro_04.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/A.Voyage.of.Chihiro_05.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/A.Voyage.of.Chihiro_06.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/A.Voyage.of.Chihiro_07.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/A.Voyage.of.Chihiro_08.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/A.Voyage.of.Chihiro_09.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/A.Voyage.of.Chihiro_10.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/A.Voyage.of.Chihiro_11.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/A.Voyage.of.Chihiro_12.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Atonement_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Atonement_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Atonement_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Atonement_04.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Avatar_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Before.Sunrise_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Before.Sunrise_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Before.Sunset_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/bighero_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/bighero_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/bighero_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Coco_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Coco_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Coco_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/CUG.King.of.Heroes_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Digimon_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Digimon_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Digimon_04.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Digimon_05.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Digimon_06.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Digimon_07.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Digimon_08.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Digimon_09.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Friends_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Friends_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Friends_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Friends_04.webp,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Friends_05.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Harry.Potter_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Harry.Potter_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Harry.Potter_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Harry.Potter_04.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Harry.Potter_05.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Hauru.no.ugoku.shiro_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Into.the.Wild_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Kaze.tachinu_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/kiki_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/kiki_03.png,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/kiki_04.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/kiminona_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/kiminona_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/kiminona_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/kiminona_06.png,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/kiminona_07.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/koenokatachi_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/koenokatachi_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/koenokatachi_03.png,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Kotonoha.no.Niwa_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/La.La.Land_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Le.Petit.Prince_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Le.Petit.Prince_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Mimi.wo.sumaseba_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Mr.Bean.Holiday_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Mr.Bean.Holiday_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Mr.Bean.Holiday_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Mr.Bean.Holiday_04.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Mr.Bean.Holiday_05.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/My.Sassy.Girl_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Paperman_01.png,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Paperman_02.png,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Piper_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Ponyo_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Ponyo_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Ponyo_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Reply.1988_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Reply.1988_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Reply.1988_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/SpiderMan.Into.the.SpiderVerse_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/SpiderMan.Into.the.SpiderVerse_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/SpiderMan.Into.the.SpiderVerse_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/The.Girl.Who.Leapt.Through.Time_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/The.Pianist_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/TheLonelyAndGreatGod_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Titanic_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Titanic_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Titanic_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/totoro1.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/WALL_E_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/WALL_E_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Zootopia_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/2049.Blade.Runner_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/2049.Blade.Runner_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/American.Dreams.in.China_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Biri.Girl_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Bohemian.Rhapsody_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Bohemian.Rhapsody_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Bohemian.Rhapsody_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Crouching.Tiger.Hidden.Dragon.2000_01.webp,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Detachment_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Detachment_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Gisaengchung_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Iron.Man_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Kureyon.Shinchan_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Love.Actually_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Roman.Holiday_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Roman.Holiday_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Sherlock.S01_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/The.Secret.Life.of.Walter.Mitty_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Youth.Over.Flowers.in.Africa_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Youth.Over.Flowers.in.Africa_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/My.Mister_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/One.Day_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/One.Day_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/One.Day_03.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Ready.Player.One_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Begin.Again_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Begin.Again_02.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/Freddie_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/naruto.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/SetoNaikai_01.jpg,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/yexiu_01.png,https://cdn.jsdelivr.net/gh/tiancixiong/BlogIMG@230521/theme/cover/yexiu_02_FUJISKYTREE.png".split(",");
  var bgindex = Math.floor(Math.random()*bg.length);
  if (!!window.ActiveXObject || "ActiveXObject" in window) { //is IE?
    alert('朋友，IE浏览器未适配哦~');
  }
  </script>
  <style type="text/css">
  .hljs-ln{border-collapse:collapse}.hljs-ln td{padding:0}.hljs-ln-n:before{content:attr(data-line-number)}
  </style>
  <style type="text/css">.site-top .lower nav{display:block !important;}.author-profile i,.post-like a,.post-share .show-share,.sub-text,.we-info a,span.sitename,.post-more i:hover,#pagination a:hover,.post-content a:hover,.float-content i:hover{color:#FE9600}.feature i,.download,.navigator i:hover,.links ul li:before,.ar-time i,span.ar-circle,.object,.comment .comment-reply-link,.siren-checkbox-radio:checked + .siren-checkbox-radioInput:after{background:#FE9600}::-webkit-scrollbar-thumb{background:#FE9600}.download,.navigator i:hover,.link-title,.links ul li:hover,#pagination a:hover,.comment-respond input[type='submit']:hover{border-color:#FE9600}.entry-content a:hover,.site-info a:hover,.comment h4 a,#comments-navi a.prev,#comments-navi a.next,.comment h4 a:hover,.site-top ul li a:hover,.entry-title a:hover,#archives-temp h3,span.page-numbers.current,.sorry li a:hover,.site-title a:hover,i.iconfont.js-toggle-search.iconsearch:hover,.comment-respond input[type='submit']:hover{color:#FE9600}.comments .comments-main{display:block !important;}.comments .comments-hidden{display:none !important;}background-position:center center;background-attachment:inherit;}
  </style>
</head>
</html>
<body class="page-template page-template-user page-template-page-analytics page-template-userpage-analytics-php page page-id-1297 chinese-font serif isWebKit">
  <div class="scrollbar" id="bar">
  </div>
  <a href="#" class="cd-top faa-float animated"></a>
  <section id="main-container">
    <div class="headertop filter-dot">
  <!--首页背景图下方的波浪线-->
  <!--<div id="banner_wave_1"></div>-->
  <!--<div id="banner_wave_2"></div>-->
  <figure id="centerbg" class="centerbg">
    <div class="focusinfo no-select">
      <div class="header-tou">
        <a href="/">
          <img src="https://fastly.jsdelivr.net/gh/tiancixiong/cdn@v1.0/img/custom/avatar.jpg">
        </a>
      </div>
      <div class="header-info">
        <p>You Only Live Once</p>
        <div class="top-social_v2">
          <li id="bg-pre">
            <img class="flipx" src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/img/other/next-b.svg">
          </li>
          
            
              
                <li>
                  <a href="https://github.com/tiancixiong" target="_blank" class="social-github" title="github">
                    <img src="https://fastly.jsdelivr.net/gh/tiancixiong/cdn@v1.0/img/social/github.png">
                  </a>
                </li>
              
            
              
                <li>
                  <a href="mailto:support@xiongtianci.com" target="_blank" class="social-github" title="E-mail">
                    <img src="https://fastly.jsdelivr.net/gh/tiancixiong/cdn@v1.0/img/social/email.svg">
                  </a>
                </li>
              
            
          
          <li id="bg-next">
            <img src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/img/other/next-b.svg">
          </li>
        </div>
      </div>
    </div>
  </figure>
  <div id="video-container" style="">
    <video style="object-fit: fill" id="bgvideo" class="video" video-name="" src="" width="auto" preload="auto">
    </video>
    <div id="video-btn" class="loadvideo videolive">
    </div>
    <div id="video-add">
    </div>
    <div class="video-stu">
    </div>
  </div>
  <div class="headertop-down faa-float animated" onclick="headertop_down()">
    <span>
      <i class="fa fa-chevron-down" aria-hidden="true">
      </i>
    </span>
  </div>
</div>
    <div id="page" class="site wrapper">
      <header class="site-header no-select gizle sabit" role="banner">
  <div class="site-top">
    <div class="site-branding">
      <span class="site-title">
        <span class="logolink moe-mashiro">
          <a href="/">
            <span class="sakurasono"></span>
            <span class="shironeko">天赐の小站</span>
          </a>
        </span>
      </span>
    </div>
    <div class="searchbox search-form-submit">
      <i class="iconfont js-toggle-search iconsearch icon-search">
      </i>
    </div>
    <div id="show-nav" class="showNav mobile-fit">
      <div class="line line1">
      </div>
      <div class="line line2">
      </div>
      <div class="line line3">
      </div>
    </div>
    <div class="lower-cantiner">
      <div class="lower">
        <nav class="mobile-fit-control hide">
          <ul id="menu-new" class="menu">
            
              <li>
                <a href="/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-fort-awesome faa-horizontal" aria-hidden="true"></i>
                    首页
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="/archives">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-terminal faa-vertical" aria-hidden="true"></i>
                    极客
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/categories/技术/">
                          <i class="fa fa-code" aria-hidden="true"></i>
                          技术
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/Linux/">
                          <i class="fa fa-linux" aria-hidden="true"></i>
                          Linux
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="/archives">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-slack faa-spin" aria-hidden="true"></i>
                    爱好
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/categories/电影/">
                          <i class="fa fa-film" aria-hidden="true"></i>
                          电影
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/日语/">
                          <i class="fa fa-language" aria-hidden="true"></i>
                          日语
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="/archives">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-archive faa-ring" aria-hidden="true"></i>
                    归档
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/categories/生活/">
                          <i class="fa fa-file-text-o" aria-hidden="true"></i>
                          生活
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/随想/">
                          <i class="fa fa-commenting-o" aria-hidden="true"></i>
                          随想
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/资源/">
                          <i class="fa fa-cloud-download" aria-hidden="true"></i>
                          资源
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/转载/">
                          <i class="fa fa-book" aria-hidden="true"></i>
                          转载
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="/comment/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-pencil-square-o faa-tada" aria-hidden="true"></i>
                    留言板
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="/links/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-link faa-shake" aria-hidden="true"></i>
                    友人帐
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="/donate/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-heart faa-burst" aria-hidden="true"></i>
                    赞赏
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-leaf faa-falling" aria-hidden="true"></i>
                    关于
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/about/">
                          <i class="fa fa-meetup" aria-hidden="true"></i>
                          我？
                        </a>
                      </li>
                    
                      <li>
                        <a href="/theme-sakura/">
                          <i class="fa iconfont icon-sakura" aria-hidden="true"></i>
                          主题
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="/atom.xml">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-rss faa-passing" aria-hidden="true"></i>
                    RSS
                  </span>
                </a>
                
              </li>
            
          </ul>
        </nav>
      </div>
    </div>
  </div>
</header>

      <link rel="stylesheet" type="text/css" href="/css/sharejs.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.css">
<div class="pattern-center-blank"></div>

  <div class="pattern-center single-center">
    <!-- 有配图默认渲染第一张 -->
    <div class="pattern-attachment-img lazyload" style="background-image: url(https://images.unsplash.com/photo-1528164344705-47542687000d?w=540);" src="https://fastly.jsdelivr.net/gh/tiancixiong/cdn@v1.0/img/loader/orange.progress-bar-stripe-loader.svg" data-src="https://images.unsplash.com/photo-1528164344705-47542687000d?w=540">
    </div>
    <header class="pattern-header single-header">
      <h1 class="entry-title">
      JUC学习笔记-异步编程：Future与Callable</h1>
      <p class="entry-census">
        <span>
          <a href="https://blog.xiongtianci.com">
            <img src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@v1.0/img/custom/avatar.jpg">
          </a>
        </span>
        <span>
          <a href="https://blog.xiongtianci.com">木浅</a>
        </span>
        <span class="bull">
        ·</span>
        2024-4-9<span class="bull">
        ·</span>
      <span id="busuanzi_value_page_pv"></span>次阅读</p>
    </header>
  </div>

<div id="content" class="site-content">
  <div id="primary" class="content-area">
    <main id="main" class="site-main" role="main">
      <article id="post-1" class="post-1 post type-post status-publish format-standard has-post-thumbnail hentry category-uncategorized">
        <div class="toc"></div>
        <!--<div class="toc-entry-content"><!-- 套嵌目录使用（主要为了支援评论）-->
        
        <div class="entry-content">
          <h1 id="Callable和Future"><a href="#Callable和Future" class="headerlink" title="Callable和Future"></a>Callable和Future</h1><ul>
<li><strong>Callable</strong> 负责 <strong>定义任务逻辑</strong>（类似 <code>Runnable</code>，但能返回结果和抛出异常）。</li>
<li><strong>Future</strong> 负责 <strong>管理任务生命周期</strong> 和 <strong>获取计算结果</strong>。</li>
<li>二者结合才能完整实现 <strong>“提交任务 → 异步执行 → 获取结果”</strong> 的流程。</li>
</ul>
<p><strong>功能互补</strong></p>
<table>
<thead>
<tr>
<th style="text-align:left"></th>
<th style="text-align:left">职责</th>
<th style="text-align:left">对方的作用</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left"><strong>Callable</strong></td>
<td style="text-align:left">定义可返回结果的任务逻辑</td>
<td style="text-align:left">需要 <code>Future</code> 来接收和管理它的计算结果</td>
</tr>
<tr>
<td style="text-align:left"><strong>Future</strong></td>
<td style="text-align:left">监控任务状态、获取结果或取消任务</td>
<td style="text-align:left">需要 <code>Callable</code> 作为实际的任务提供者</td>
</tr>
</tbody>
</table>
<pre><code class="java">// 典型使用场景
ExecutorService executor = Executors.newCachedThreadPool();
Callable&lt;String&gt; task = () -&gt; &quot;Hello World&quot;;  // 定义任务
Future&lt;String&gt; future = executor.submit(task); // 提交任务并获取Future
String result = future.get();                  // 通过Future获取结果
</code></pre>
<h1 id="Callable接口"><a href="#Callable接口" class="headerlink" title="Callable接口"></a>Callable接口</h1><p>Callable是Java 5引入的接口，与Runnable类似，但有三个关键区别：</p>
<pre><code class="java">public interface Callable&lt;V&gt; {
    V call() throws Exception;
}
</code></pre>
<ul>
<li>可以返回结果（泛型V）</li>
<li>可以抛出受检异常</li>
<li>需要实现 <code>call()</code> 方法而非 <code>run()</code></li>
</ul>
<p>与 Runnable 的对比</p>
<table>
<thead>
<tr>
<th style="text-align:left">特性</th>
<th style="text-align:left">Callable</th>
<th style="text-align:left">Runnable</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">返回值</td>
<td style="text-align:left">支持</td>
<td style="text-align:left">不支持</td>
</tr>
<tr>
<td style="text-align:left">异常</td>
<td style="text-align:left">可以抛出受检异常</td>
<td style="text-align:left">不能抛出受检异常</td>
</tr>
<tr>
<td style="text-align:left">方法签名</td>
<td style="text-align:left">V call() throws Exception</td>
<td style="text-align:left">void run()</td>
</tr>
<tr>
<td style="text-align:left">使用场景</td>
<td style="text-align:left">需要返回结果的异步任务</td>
<td style="text-align:left">简单的异步操作</td>
</tr>
</tbody>
</table>
<h2 id="Callable的基本使用"><a href="#Callable的基本使用" class="headerlink" title="Callable的基本使用"></a>Callable的基本使用</h2><p>基本用法示例：</p>
<pre><code class="java">// 创建Callable任务
Callable&lt;Integer&gt; task = () -&gt; {
    int sum = 0;
    for (int i = 1; i &lt;= 10; i++) {
        sum += i;
        Thread.sleep(100); // 模拟耗时操作
    }
    return sum;
};

// 使用FutureTask包装Callable
FutureTask&lt;Integer&gt; futureTask = new FutureTask&lt;&gt;(task);

// 启动线程执行任务
new Thread(futureTask).start();

try {
    // 获取计算结果（会阻塞直到计算完成）
    int result = futureTask.get();
    System.out.println(&quot;1到10的和为: &quot; + result);
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}
</code></pre>
<p>与 ExecutorService 结合使用：</p>
<pre><code class="java">// 创建线程池
ExecutorService executor = Executors.newFixedThreadPool(4);

// 创建Callable任务列表
List&lt;Callable&lt;Integer&gt;&gt; tasks = new ArrayList&lt;&gt;();
for (int i = 0; i &lt; 10; i++) {
    final int taskId = i;
    tasks.add(() -&gt; {
        System.out.println(&quot;任务&quot; + taskId + &quot;开始执行&quot;);
        Thread.sleep(1000); // 模拟耗时操作
        return taskId * taskId; // 返回平方值
    });
}

try {
    // 提交所有任务并获取Future列表
    List&lt;Future&lt;Integer&gt;&gt; futures = executor.invokeAll(tasks);

    // 处理结果
    for (Future&lt;Integer&gt; future : futures) {
        System.out.println(&quot;任务结果: &quot; + future.get());
    }
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
} finally {
    // 关闭线程池
    executor.shutdown();
}
</code></pre>
<h2 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h2><p><strong>场景1：并行计算</strong></p>
<pre><code class="java">import java.util.concurrent.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class ParallelComputation {
    public static void main(String[] args) {
        List&lt;Integer&gt; numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        ExecutorService executor = Executors.newFixedThreadPool(4);

        try {
            // 并行计算每个数字的阶乘
            List&lt;Future&lt;Long&gt;&gt; futures = executor.invokeAll(
                    numbers.stream()
                            .map(n -&gt; (Callable&lt;Long&gt;) () -&gt; factorial(n))
                            .collect(Collectors.toList())
            );

            for (int i = 0; i &lt; numbers.size(); i++) {
                System.out.printf(&quot;%d! = %d%n&quot;, numbers.get(i), futures.get(i).get());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }

    private static long factorial(int n) {
        if (n == 0) return 1;
        long result = 1;
        for (int i = 1; i &lt;= n; i++) {
            result *= i;
            try {
                Thread.sleep(100); // 模拟计算耗时
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        return result;
    }
}
</code></pre>
<p><strong>场景2：超时控制</strong></p>
<pre><code class="java">import java.util.concurrent.*;

public class TimeoutExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        Callable&lt;String&gt; task = () -&gt; {
            Thread.sleep(2000); // 模拟长时间运行的任务
            return &quot;任务完成&quot;;
        };

        Future&lt;String&gt; future = executor.submit(task);

        try {
            // 设置1秒超时
            String result = future.get(1, TimeUnit.SECONDS);
            System.out.println(result);
        } catch (TimeoutException e) {
            System.out.println(&quot;任务超时，取消任务&quot;);
            future.cancel(true); // 尝试中断任务
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }
}
</code></pre>
<p><strong>场景3：多个任务竞争（获取第一个完成的结果）</strong></p>
<pre><code class="java">import java.util.concurrent.*;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

public class FirstCompletedExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();

        List&lt;Callable&lt;String&gt;&gt; tasks = Arrays.asList(
            () -&gt; { Thread.sleep(new Random().nextInt(1000)); return &quot;任务1完成&quot;; },
            () -&gt; { Thread.sleep(new Random().nextInt(1000)); return &quot;任务2完成&quot;; },
            () -&gt; { Thread.sleep(new Random().nextInt(1000)); return &quot;任务3完成&quot;; }
        );

        try {
            // 获取第一个完成的任务结果
            String result = executor.invokeAny(tasks);
            System.out.println(&quot;第一个完成的任务: &quot; + result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }
}
</code></pre>
<h1 id="Future接口"><a href="#Future接口" class="headerlink" title="Future接口"></a>Future接口</h1><p>Future是Java并发编程中一个非常重要的接口，它位于 <code>java.util.concurrent</code> 包中。Future 表示一个异步计算的结果，它提供了检查计算是否完成的方法，以及等待计算完成并检索其结果的方法。</p>
<p>Future接口为Java并发编程提供了基础的异步计算支持，通过它可以：</p>
<ul>
<li>提交任务并获取未来可能的结果</li>
<li>查询任务状态和取消任务</li>
<li>实现任务的超时控制</li>
</ul>
<pre><code class="java">package java.util.concurrent;

public interface Future&lt;V&gt; {
    // 尝试取消任务的执行
    boolean cancel(boolean mayInterruptIfRunning);

    // 判断任务是否被取消
    boolean isCancelled();

    // 判断任务是否完成
    boolean isDone();

    // 获取计算结果（阻塞直到计算完成）
    V get() throws InterruptedException, ExecutionException;

    // 获取计算结果（带超时限制）
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}
</code></pre>
<ul>
<li><strong>isCancelled()</strong>：只有任务未启动，或者在完成之前被取消，才会返回true，表示任务已经被成功取消。其他情况都会返回false</li>
<li><strong>get()</strong>：方法是阻塞的，可能会影响系统响应性。使用带超时的 <code>get()</code> 方法避免无限期等待</li>
</ul>
<h2 id="Future的使用"><a href="#Future的使用" class="headerlink" title="Future的使用"></a>Future的使用</h2><h3 id="基本使用"><a href="#基本使用" class="headerlink" title="基本使用"></a>基本使用</h3><p><strong>案例1：基本使用</strong></p>
<pre><code class="java">import java.util.concurrent.*;

public class FutureBasicDemo {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        // 提交Callable任务，返回Future对象
        Future&lt;String&gt; future = executor.submit(() -&gt; {
            Thread.sleep(2000); // 模拟耗时操作
            return &quot;Hello, Future!&quot;;
        });

        System.out.println(&quot;任务已提交，可以继续做其他事情...&quot;);

        // 检查任务是否完成
        if (!future.isDone()) {
            System.out.println(&quot;任务还未完成，可以继续处理其他逻辑&quot;);
        }

        // 获取结果（会阻塞直到任务完成）
        String result = future.get();
        System.out.println(&quot;获取到结果: &quot; + result);

        executor.shutdown();
    }
}
</code></pre>
<p><strong>案例2：超时控制</strong></p>
<pre><code class="java">import java.util.concurrent.*;

public class FutureTimeoutDemo {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        Future&lt;String&gt; future = executor.submit(() -&gt; {
            Thread.sleep(3000);
            return &quot;Result after long processing&quot;;
        });

        try {
            // 设置超时时间为2秒
            String result = future.get(2, TimeUnit.SECONDS);
            System.out.println(&quot;结果: &quot; + result);
        } catch (TimeoutException e) {
            System.out.println(&quot;任务执行超时&quot;);
            future.cancel(true); // 取消任务
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }
}
</code></pre>
<p><strong>案例3：任务取消</strong></p>
<pre><code class="java">import java.util.concurrent.*;

public class FutureCancelDemo {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        Future&lt;String&gt; future = executor.submit(() -&gt; {
            Thread.sleep(5000);
            return &quot;This should not be reached if cancelled&quot;;
        });

        // 模拟执行一段时间后决定取消任务
        Thread.sleep(1000);

        // 尝试取消任务（参数true表示可以中断正在执行的任务）
        boolean cancelled = future.cancel(true);
        System.out.println(&quot;任务取消&quot; + (cancelled ? &quot;成功&quot; : &quot;失败&quot;));

        // 检查任务状态
        System.out.println(&quot;任务是否取消: &quot; + future.isCancelled());
        System.out.println(&quot;任务是否完成: &quot; + future.isDone());

        try {
            // 尝试获取已取消任务的结果会抛出CancellationException
            String result = future.get();
            System.out.println(result);
        } catch (CancellationException e) {
            System.out.println(&quot;无法获取结果，任务已被取消&quot;);
        }

        executor.shutdown();
    }
}
</code></pre>
<h3 id="应用场景-1"><a href="#应用场景-1" class="headerlink" title="应用场景"></a>应用场景</h3><p><strong>场景1：并行处理多个任务</strong></p>
<pre><code class="java">import java.util.concurrent.*;

public class MultipleFuturesDemo {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        // 提交多个任务
        Future&lt;String&gt; future1 = executor.submit(() -&gt; {
            Thread.sleep(1000);
            return &quot;Result from Task 1&quot;;
        });

        Future&lt;String&gt; future2 = executor.submit(() -&gt; {
            Thread.sleep(1500);
            return &quot;Result from Task 2&quot;;
        });

        Future&lt;String&gt; future3 = executor.submit(() -&gt; {
            Thread.sleep(800);
            return &quot;Result from Task 3&quot;;
        });

        // 获取所有结果（会按调用顺序阻塞）
        System.out.println(future1.get());
        System.out.println(future2.get());
        System.out.println(future3.get());

        executor.shutdown();
    }
}
</code></pre>
<p><strong>场景2：电商价格聚合案例</strong></p>
<pre><code class="java">import java.util.concurrent.*;

public class PriceAggregator {
    private ExecutorService executor = Executors.newFixedThreadPool(3);

    public double getFinalPrice(String product) throws Exception {
        // 并行获取不同平台的价格
        Future&lt;Double&gt; taobaoPrice = executor.submit(() -&gt; getPriceFromTaobao(product));
        Future&lt;Double&gt; jdPrice = executor.submit(() -&gt; getPriceFromJD(product));
        Future&lt;Double&gt; pddPrice = executor.submit(() -&gt; getPriceFromPDD(product));

        // 模拟其他处理
        System.out.println(&quot;正在处理其他业务逻辑...&quot;);
        Thread.sleep(500);

        // 获取所有价格并计算最低价
        double finalPrice = Math.min(taobaoPrice.get(), Math.min(jdPrice.get(), pddPrice.get()));

        return finalPrice;
    }

    private double getPriceFromTaobao(String product) throws InterruptedException {
        Thread.sleep(1000);
        return 199.0; // 模拟价格
    }

    private double getPriceFromJD(String product) throws InterruptedException {
        Thread.sleep(1200);
        return 219.0; // 模拟价格
    }

    private double getPriceFromPDD(String product) throws InterruptedException {
        Thread.sleep(800);
        return 189.0; // 模拟价格
    }

    public static void main(String[] args) throws Exception {
        PriceAggregator aggregator = new PriceAggregator();
        double price = aggregator.getFinalPrice(&quot;iPhone 13&quot;);
        System.out.println(&quot;最终价格: &quot; + price);
        aggregator.executor.shutdown();
    }
}
</code></pre>
<h1 id="Future实现类"><a href="#Future实现类" class="headerlink" title="Future实现类"></a>Future实现类</h1><p>JUC 并发包中，Future 接口有几个重要的实现类，每个实现类都有其特定的使用场景和优势：</p>
<ol>
<li><strong>FutureTask</strong>：最基础的 Future 实现，同时实现了 Runnable 接口</li>
<li><strong>ScheduledFuture</strong>：用于定时任务的 Future 实现</li>
<li><strong>ForkJoinTask</strong>：Fork/Join 框架中的 Future 实现</li>
<li><strong>CompletableFuture</strong>（Java 8+）：功能最丰富的Future实现</li>
</ol>
<h2 id="FutureTask"><a href="#FutureTask" class="headerlink" title="FutureTask"></a>FutureTask</h2><p>FutureTask 是 Future 接口的一个实现类，特点：</p>
<ul>
<li>同时实现了 Future 和 Runnable 接口，因此可作为任务提交给线程池 <code>Executor</code> 执行</li>
<li>只能执行一次，不能重复使用</li>
<li>内部基于AQS（AbstractQueuedSynchronizer）实现状态控制</li>
</ul>
<p><strong>示例</strong>：</p>
<pre><code class="java">import java.util.concurrent.FutureTask;

public class FutureTaskDemo {
    public static void main(String[] args) throws Exception {
        // 创建FutureTask
        FutureTask&lt;Integer&gt; futureTask = new FutureTask&lt;&gt;(() -&gt; {
            int sum = 0;
            for (int i = 0; i &lt; 100; i++) {
                sum += i;
                Thread.sleep(10);
            }
            return sum;
        });

        // 创建线程执行FutureTask
        new Thread(futureTask).start();

        // 主线程可以继续做其他事情
        System.out.println(&quot;主线程正在处理其他任务...&quot;);
        Thread.sleep(500);

        // 获取计算结果
        if (!futureTask.isDone()) {
            System.out.println(&quot;计算任务还未完成，请稍候...&quot;);
        }

        int result = futureTask.get();
        System.out.println(&quot;计算结果: &quot; + result);
    }
}
</code></pre>
<p><strong>案例：缓存系统实现</strong></p>
<p>基于 FutureTask 实现的高并发缓存系统，解决了缓存系统中常见的”缓存击穿”问题，并提供了线程安全的缓存访问机制：</p>
<pre><code class="java">import java.math.BigInteger;
import java.util.Map;
import java.util.concurrent.*;

public class CacheSystem&lt;K, V&gt; {
    private final Map&lt;K, FutureTask&lt;V&gt;&gt; cache = new ConcurrentHashMap&lt;&gt;();
    private final Computable&lt;K, V&gt; computable;

    public CacheSystem(Computable&lt;K, V&gt; computable) {
        this.computable = computable;
    }

    public V get(final K key) throws InterruptedException {
        while (true) {
            FutureTask&lt;V&gt; future = cache.get(key);
            if (future == null) {
                FutureTask&lt;V&gt; newTask = new FutureTask&lt;&gt;(() -&gt; computable.compute(key));
                future = cache.putIfAbsent(key, newTask);
                if (future == null) {
                    future = newTask;
                    future.run(); // 开始计算
                }
            }

            try {
                return future.get();
            } catch (CancellationException e) {
                cache.remove(key);
            } catch (ExecutionException e) {
                throw launderThrowable(e.getCause());
            }
        }
    }

    private RuntimeException launderThrowable(Throwable t) {
        if (t instanceof RuntimeException) return (RuntimeException) t;
        else if (t instanceof Error) throw (Error) t;
        else throw new IllegalStateException(&quot;Not unchecked&quot;, t);
    }

    public interface Computable&lt;K, V&gt; {
        V compute(K key) throws InterruptedException;
    }
}

// 使用示例
class CacheDemo {
    public static void main(String[] args) {
        CacheSystem&lt;String, BigInteger&gt; cache = new CacheSystem&lt;&gt;(key -&gt; {
            // 模拟耗时计算
            Thread.sleep(1000);
            return new BigInteger(key);
        });

        ExecutorService executor = Executors.newFixedThreadPool(10);
        for (int i = 0; i &lt; 10; i++) {
            final String key = &quot;12345&quot;;
            executor.execute(() -&gt; {
                try {
                    System.out.println(Thread.currentThread().getName() +
                            &quot; 获取结果: &quot; + cache.get(key));
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        executor.shutdown();
    }
}
</code></pre>
<p>工作流程：</p>
<pre><code>[客户端调用get(key)]
       |
       v
检查缓存是否存在 --&gt; 存在 --&gt; 返回缓存结果
       |
       v
不存在 --&gt; 创建FutureTask --&gt; 放入缓存 --&gt; 执行计算
       |
       v
其他线程再次请求相同key --&gt; 获取已存在的FutureTask --&gt; 等待计算结果
</code></pre><p>使用场景：</p>
<pre><code class="java">// 电商系统-商品详情缓存
CacheSystem&lt;Long, ProductDetail&gt; productCache = new CacheSystem&lt;&gt;(productId -&gt; {
    // 从数据库获取商品详情（耗时操作）
    return productDao.getDetailById(productId);
});

// 获取商品详情（数万QPS场景下能有效防止缓存击穿）
ProductDetail detail = productCache.get(12345L);
</code></pre>
<h2 id="ScheduledFuture与定时任务"><a href="#ScheduledFuture与定时任务" class="headerlink" title="ScheduledFuture与定时任务"></a>ScheduledFuture与定时任务</h2><p>ScheduledFuture 用于表示延迟或周期性任务的执行结果，通常与 <code>ScheduledExecutorService</code> 配合使用。</p>
<p><strong>核心特性</strong>：</p>
<ul>
<li><strong>延迟/周期性任务</strong>：支持固定延迟（<code>scheduleWithFixedDelay</code>）或固定速率（<code>scheduleAtFixedRate</code>）的任务调度。</li>
<li><strong>继承自 <code>Future</code></strong>：提供任务取消、结果获取等基础功能。</li>
<li><strong>时间控制</strong>：通过 <code>getDelay()</code> 方法获取剩余延迟时间。</li>
</ul>
<p><strong>示例</strong>：</p>
<pre><code class="java">ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
ScheduledFuture&lt;?&gt; future = executor.schedule(
        () -&gt; System.out.println(&quot;Task executed after 1 second&quot;),
        1, TimeUnit.SECONDS
);
</code></pre>
<p><strong>案例：订单超时取消</strong></p>
<pre><code class="java">import java.util.Map;
import java.util.concurrent.*;

public class OrderTimeoutSystem {
    private final ScheduledExecutorService scheduler =
            Executors.newScheduledThreadPool(1);
    private final Map&lt;Long, ScheduledFuture&lt;?&gt;&gt; orderTasks = new ConcurrentHashMap&lt;&gt;();

    public void placeOrder(long orderId) {
        // 提交定时任务，30分钟后检查订单状态
        ScheduledFuture&lt;?&gt; future = scheduler.schedule(() -&gt; {
            if (!isOrderPaid(orderId)) {
                cancelOrder(orderId);
                orderTasks.remove(orderId);
            }
        }, 30, TimeUnit.MINUTES);

        orderTasks.put(orderId, future);
    }

    public void orderPaid(long orderId) {
        ScheduledFuture&lt;?&gt; future = orderTasks.get(orderId);
        if (future != null) {
            future.cancel(false); // 订单已支付，取消定时任务
            orderTasks.remove(orderId);
        }
    }

    private boolean isOrderPaid(long orderId) {
        // 查询数据库或缓存
        return false;
    }

    private void cancelOrder(long orderId) {
        System.out.println(&quot;订单超时取消: &quot; + orderId);
        // 实际业务中会更新订单状态等操作
    }

    public void shutdown() {
        scheduler.shutdown();
    }
}

// 使用示例
class OrderTimeoutDemo {
    public static void main(String[] args) throws InterruptedException {
        OrderTimeoutSystem system = new OrderTimeoutSystem();

        // 模拟订单创建
        long orderId = 10001L;
        system.placeOrder(orderId);
        System.out.println(&quot;订单创建: &quot; + orderId);

        // 模拟15分钟后支付
        Thread.sleep(TimeUnit.MINUTES.toMillis(15));
        system.orderPaid(orderId);
        System.out.println(&quot;订单已支付: &quot; + orderId);

        system.shutdown();
    }
}
</code></pre>
<h2 id="ForkJoinTask"><a href="#ForkJoinTask" class="headerlink" title="ForkJoinTask"></a>ForkJoinTask</h2><p>用途：支持分治（Divide-and-Conquer）任务的抽象基类，通常用于 <code>ForkJoinPool</code> 中处理递归或并行任务。</p>
<p><strong>核心特性</strong>：</p>
<ul>
<li><strong>分治策略</strong>：通过 <code>fork()</code> 分解任务，<code>join()</code> 合并结果。</li>
<li><strong>自动负载均衡</strong>：<code>ForkJoinPool</code> 使用工作窃取（Work-Stealing）算法，空闲线程从忙碌线程的队列尾部窃取任务。</li>
<li><strong>两种子类</strong>：<ul>
<li><code>RecursiveTask</code>：返回结果的任务。</li>
<li><code>RecursiveAction</code>：无返回结果的任务。</li>
</ul>
</li>
</ul>
<p><strong>示例</strong>（计算斐波那契数列）：</p>
<blockquote>
<p>斐波那契数列的定义：</p>
<ul>
<li><code>F(0) = 0</code></li>
<li><code>F(1) = 1</code></li>
<li><code>F(n) = F(n-1) + F(n-2)</code> （当 <code>n &gt; 1</code> 时）<br>例如：<code>0, 1, 1, 2, 3, 5, 8, 13...</code></li>
</ul>
</blockquote>
<pre><code class="java">import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

class FibonacciTask extends RecursiveTask&lt;Integer&gt; {
    final int n;

    FibonacciTask(int n) {
        this.n = n;
    }

    protected Integer compute() {
        if (n &lt;= 1) return n;
        FibonacciTask f1 = new FibonacciTask(n - 1);
        f1.fork(); // 分解任务
        FibonacciTask f2 = new FibonacciTask(n - 2);
        return f2.compute() + f1.join(); // 合并结果
    }
}

class FibonacciTest {
    public static void main(String[] args) {
        int n = 10; // 计算斐波那契数列的第10项
        ForkJoinPool pool = new ForkJoinPool(); // 创建ForkJoin线程池
        FibonacciTask task = new FibonacciTask(n);
        int result = pool.invoke(task); // 提交任务并获取结果
        System.out.println(&quot;F(&quot; + n + &quot;) = &quot; + result); // 输出结果
        pool.shutdown(); // 关闭线程池
    }
}
</code></pre>
<p>分治逻辑：</p>
<ul>
<li>将问题拆解为计算 <code>F(n-1)</code> 和 <code>F(n-2)</code> 的子任务。</li>
<li><code>fork()</code> 提交一个子任务到线程池异步执行，<code>compute()</code> 同步执行另一个子任务。</li>
<li><code>join()</code> 等待异步任务的完成并获取结果。</li>
</ul>
<p><strong>案例：统计大量字符串出现的频率</strong></p>
<pre><code class="java">import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

public class DataProcessor extends RecursiveTask&lt;Map&lt;String, Integer&gt;&gt; {
    // 任务拆分的阈值，当 数据量≤1000 时直接处理
    private static final int THRESHOLD = 1000;
    private final List&lt;String&gt; data; // 待处理的字符串列表

    public DataProcessor(List&lt;String&gt; data) {
        this.data = data;
    }

    /**
     *
     * @return 一个统计字符串频率的 Map
     */
    @Override
    protected Map&lt;String, Integer&gt; compute() {
        if (data.size() &lt;= THRESHOLD) {
            return processDirectly(); // 数据量小，直接统计
        } else {
            int mid = data.size() / 2;
            DataProcessor leftTask = new DataProcessor(data.subList(0, mid));
            DataProcessor rightTask = new DataProcessor(data.subList(mid, data.size()));

            leftTask.fork(); // 异步提交左半部分任务
            Map&lt;String, Integer&gt; rightResult = rightTask.compute(); // 同步处理右半部分
            Map&lt;String, Integer&gt; leftResult = leftTask.join(); // 等待左半部分结果

            // 合并左右结果
            rightResult.forEach((k, v) -&gt;
                    leftResult.merge(k, v, Integer::sum));
            return leftResult;
        }
    }

    // 遍历列表，使用 map.merge 方法统计词频
    private Map&lt;String, Integer&gt; processDirectly() {
        Map&lt;String, Integer&gt; result = new HashMap&lt;&gt;();
        for (String item : data) {
            result.merge(item, 1, Integer::sum);
        }
        return result;
    }
}

// 使用示例
class ForkJoinDemo {
    public static void main(String[] args) {
        // 模拟大数据集。生成 10_000 个随机字符串（格式为 item-0 到 item-99）
        List&lt;String&gt; bigData = new ArrayList&lt;&gt;();
        for (int i = 0; i &lt; 10_000; i++) {
            bigData.add(&quot;item-&quot; + ThreadLocalRandom.current().nextInt(100));
        }

        ForkJoinPool pool = new ForkJoinPool();
        DataProcessor task = new DataProcessor(bigData);
        Map&lt;String, Integer&gt; result = pool.invoke(task);

        System.out.println(&quot;处理结果大小: &quot; + result.size());
        // 按词频降序排序，输出前5个高频词
        result.entrySet().stream()
                .sorted(Map.Entry.&lt;String, Integer&gt;comparingByValue().reversed())
                .limit(5)
                .forEach(e -&gt; System.out.println(e.getKey() + &quot;: &quot; + e.getValue()));
    }
}
</code></pre>
<h2 id="CompletableFuture"><a href="#CompletableFuture" class="headerlink" title="CompletableFuture"></a>CompletableFuture</h2><p><code>CompletableFuture</code> 是 Java 8 引入的异步编程工具。</p>
<p><strong>用途</strong>：支持异步任务的链式调用、组合和异常处理，是 <code>Future</code> 的增强版。</p>
<p><strong>核心特性</strong>：</p>
<ul>
<li><strong>非阻塞回调</strong>：通过 <code>thenApply</code>、<code>thenAccept</code> 等方法链式处理结果。</li>
<li><strong>任务组合</strong>：支持 <code>thenCombine</code>、<code>allOf</code>、<code>anyOf</code> 等多任务协作。</li>
<li><strong>异常处理</strong>：通过 <code>exceptionally</code> 或 <code>handle</code> 方法捕获异常。</li>
<li><strong>手动完成</strong>：可通过 <code>complete()</code> 或 <code>completeExceptionally()</code> 主动干预任务状态。</li>
</ul>
<p><strong>适用场景</strong></p>
<ol>
<li><strong>并行执行多个任务</strong>（如调用多个微服务）。</li>
<li><strong>异步任务编排</strong>（如 A 完成后触发 B）。</li>
<li><strong>超时控制</strong>（<code>orTimeout</code>, <code>completeOnTimeout</code>）。</li>
<li><strong>异常恢复</strong>（<code>exceptionally</code>, <code>handle</code>）。</li>
</ol>
<p>常用方法：</p>
<table>
<thead>
<tr>
<th style="text-align:left">方法</th>
<th style="text-align:left">用途</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left"><code>supplyAsync</code> / <code>runAsync</code></td>
<td style="text-align:left">创建异步任务</td>
</tr>
<tr>
<td style="text-align:left"><code>thenApply</code> / <code>thenAccept</code> / <code>thenRun</code></td>
<td style="text-align:left">链式回调</td>
</tr>
<tr>
<td style="text-align:left"><code>thenCompose</code></td>
<td style="text-align:left">链式嵌套 Future</td>
</tr>
<tr>
<td style="text-align:left"><code>thenCombine</code> / <code>allOf</code> / <code>anyOf</code></td>
<td style="text-align:left">组合多个 Future</td>
</tr>
<tr>
<td style="text-align:left"><code>exceptionally</code> / <code>handle</code></td>
<td style="text-align:left">异常处理</td>
</tr>
<tr>
<td style="text-align:left"><code>complete</code> / <code>completeExceptionally</code></td>
<td style="text-align:left">手动控制 Future</td>
</tr>
</tbody>
</table>
<p><strong>示例</strong>：</p>
<pre><code class="java">CompletableFuture.supplyAsync(() -&gt; &quot;Hello&quot;)
    .thenApply(s -&gt; s + &quot; World&quot;)
    .thenAccept(System.out::println)
    .exceptionally(ex -&gt; { ex.printStackTrace(); return null; });
</code></pre>
<h3 id="执行异步任务"><a href="#执行异步任务" class="headerlink" title="执行异步任务"></a>执行异步任务</h3><p>1、<code>supplyAsync</code> - 执行有返回值的异步任务</p>
<pre><code class="java">// 异步获取用户信息
CompletableFuture&lt;String&gt; getUserInfo = CompletableFuture.supplyAsync(() -&gt; {
    // 模拟网络请求
    try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
    return &quot;User: Alice, Age: 25&quot;;
});

System.out.println(getUserInfo.get()); // 阻塞获取结果
</code></pre>
<ul>
<li><p>默认使用 <code>ForkJoinPool.commonPool()</code>。</p>
</li>
<li><p>可指定自定义线程池：</p>
<pre><code class="java">ExecutorService executor = Executors.newFixedThreadPool(4);
CompletableFuture&lt;String&gt; future = CompletableFuture.supplyAsync(() -&gt; &quot;Task&quot;, executor);
</code></pre>
</li>
</ul>
<p>2、<code>runAsync</code> - 执行无返回值的异步任务</p>
<pre><code class="java">// 异步记录日志
CompletableFuture&lt;Void&gt; logTask = CompletableFuture.runAsync(() -&gt; {
    System.out.println(&quot;Logging operation completed at &quot; + System.currentTimeMillis());
});

logTask.join(); // 等待任务完成
</code></pre>
<h3 id="链式调用（回调处理）"><a href="#链式调用（回调处理）" class="headerlink" title="链式调用（回调处理）"></a>链式调用（回调处理）</h3><p>链式调用（Chaining Calls）允许以<strong>流水线（Pipeline）</strong>的方式将多个异步操作串联起来，形成清晰的任务处理流程。</p>
<p><strong>将多个操作通过方法连续调用的方式连接在一起</strong>，前一个操作的输出作为后一个操作的输入，形成”任务流水线”。</p>
<p>1、<code>thenApply</code> - 转换结果，对前一个任务的结果进行转换。</p>
<pre><code class="java">// 异步获取用户名后转为大写
CompletableFuture&lt;String&gt; upperCaseName = CompletableFuture.supplyAsync(() -&gt; &quot;alice&quot;)
    .thenApply(name -&gt; name.toUpperCase());

System.out.println(upperCaseName.get()); // &quot;ALICE&quot;
</code></pre>
<p>2、<code>thenAccept</code> - 消费结果，获取前一个任务的结果并进行消费（无返回值）。</p>
<pre><code class="java">// 异步查询订单后发送邮件
CompletableFuture.supplyAsync(() -&gt; &quot;Order#12345&quot;)
    .thenAccept(order -&gt; System.out.println(&quot;Sending confirmation for &quot; + order));
</code></pre>
<p>3、<code>thenRun</code> - 任务完成后执行操作，前一个任务完成后执行某个操作，不关心结果。</p>
<pre><code class="java">// 数据库备份完成后通知管理员
CompletableFuture.runAsync(() -&gt; backupDatabase())
    .thenRun(() -&gt; System.out.println(&quot;Notifying admin: Backup complete&quot;));
</code></pre>
<p>4、<code>thenCompose</code> - 链式嵌套 Future，用于链式调用多个 <code>CompletableFuture</code>，避免回调地狱。</p>
<pre><code class="java">// 先查用户ID，再查用户详情
CompletableFuture&lt;Integer&gt; userIdFuture = CompletableFuture.supplyAsync(() -&gt; 1001);

CompletableFuture&lt;String&gt; userDetailFuture = userIdFuture.thenCompose(id -&gt; 
    CompletableFuture.supplyAsync(() -&gt; &quot;User Details for ID: &quot; + id)
);

System.out.println(userDetailFuture.get()); // &quot;User Details for ID: 1001&quot;
</code></pre>
<hr>
<p><strong>Q1：<code>thenApply</code> 和 <code>thenCompose</code> 的区别？</strong></p>
<ul>
<li><p><code>thenApply</code>：接收前序结果，返回<strong>普通值</strong></p>
<pre><code class="java">.thenApply(v -&gt; v.toUpperCase()) // 返回 String
</code></pre>
</li>
<li><p><code>thenCompose</code>：接收前序结果，返回<strong>新的 CompletableFuture</strong></p>
<pre><code class="java">.thenCompose(v -&gt; queryFromDB(v)) // 返回 CompletableFuture&lt;String&gt;
</code></pre>
</li>
</ul>
<p><strong>Q2：电商订单处理链</strong></p>
<pre><code class="java">// 1. 查询用户信息 → 2. 查询商品 → 3. 计算价格 → 4. 生成订单
CompletableFuture.supplyAsync(() -&gt; getUser(userId))
    .thenApply(user -&gt; getProduct(user, productId))
    .thenApply(product -&gt; calculatePrice(product))
    .thenAccept(price -&gt; createOrder(price))
    .exceptionally(ex -&gt; {
        log.error(&quot;Order failed&quot;, ex);
        return null;
    });
</code></pre>
<h3 id="组合多个Future"><a href="#组合多个Future" class="headerlink" title="组合多个Future"></a>组合多个Future</h3><p>1、<code>thenCombine</code> - 合并两个 Future 的结果，等待两个任务完成，并对结果进行合并。</p>
<pre><code class="java">// 并行查询商品价格和库存，然后计算总价值
CompletableFuture&lt;Double&gt; priceFuture = CompletableFuture.supplyAsync(() -&gt; 19.99);
CompletableFuture&lt;Integer&gt; stockFuture = CompletableFuture.supplyAsync(() -&gt; 100);

CompletableFuture&lt;BigDecimal&gt; totalValue = priceFuture.thenCombine(stockFuture,
        (price, stock) -&gt; new BigDecimal(String.valueOf(price)).multiply(new BigDecimal(stock))
);

System.out.println(totalValue.get().toString()); // 1999.0
</code></pre>
<p>2、<code>allOf</code> - 等待所有 Future 完成。并行执行多个任务，并在所有任务完成后触发回调。</p>
<pre><code class="java">// 批量调用多个API，全部完成后处理数据
CompletableFuture&lt;String&gt; api1 = CompletableFuture.supplyAsync(() -&gt; &quot;Data1&quot;);
CompletableFuture&lt;String&gt; api2 = CompletableFuture.supplyAsync(() -&gt; &quot;Data2&quot;);
CompletableFuture&lt;String&gt; api3 = CompletableFuture.supplyAsync(() -&gt; &quot;Data3&quot;);

CompletableFuture&lt;Void&gt; allApis = CompletableFuture.allOf(api1, api2, api3);

allApis.thenRun(() -&gt; {
    System.out.println(&quot;All APIs completed&quot;);
    // 获取各个任务的结果
    try {
        String result1 = api1.get();
        String result2 = api2.get();
        String result3 = api3.get();
        System.out.println(result1 + &quot;, &quot; + result2 + &quot;, &quot; + result3);
    } catch (Exception e) {
        e.printStackTrace();
    }
});
</code></pre>
<p>3、<code>anyOf</code> - 任意一个 Future 完成时触发。多个任务竞争，只要有一个完成就触发回调。</p>
<pre><code class="java">// 多个服务提供相同数据，取最先返回的
CompletableFuture&lt;String&gt; serviceA = CompletableFuture.supplyAsync(() -&gt; {
    try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
    return &quot;Service A Result&quot;;
});

CompletableFuture&lt;String&gt; serviceB = CompletableFuture.supplyAsync(() -&gt; {
    try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
    return &quot;Service B Result&quot;;
});

CompletableFuture&lt;Object&gt; fastestResult = CompletableFuture.anyOf(serviceA, serviceB);

System.out.println(fastestResult.get()); // &quot;Service B Result&quot;（因为B更快）
</code></pre>
<h3 id="异常处理"><a href="#异常处理" class="headerlink" title="异常处理"></a>异常处理</h3><p>1、<code>exceptionally</code> - 捕获异常并返回默认值。类似于 <code>try-catch</code>，在异常时提供备用值。</p>
<pre><code class="java">// 查询用户信息失败时返回默认用户
CompletableFuture&lt;String&gt; userFuture = CompletableFuture.supplyAsync(() -&gt; {
    if (Math.random() &gt; 0.5) {
        throw new RuntimeException(&quot;Failed to fetch user&quot;);
    }
    return &quot;User Data&quot;;
}).exceptionally(ex -&gt; {
    System.err.println(&quot;Error: &quot; + ex.getMessage());
    return &quot;Default User&quot;;
});

System.out.println(userFuture.get());
</code></pre>
<p>2、<code>handle</code> - 无论成功或失败都处理。无论任务成功还是失败，都会执行回调。</p>
<pre><code class="java">// 处理任务结果或异常
CompletableFuture&lt;Integer&gt; parsedFuture = CompletableFuture.supplyAsync(() -&gt; &quot;123&quot;)
    .handle((str, ex) -&gt; {
        if (ex != null) {
            return -1; // 解析失败返回默认值
        }
        try {
            return Integer.parseInt(str);
        } catch (NumberFormatException e) {
            return -1;
        }
    });

System.out.println(parsedFuture.get()); // 123 或 -1（如果异常）
</code></pre>
<h3 id="手动控制Future"><a href="#手动控制Future" class="headerlink" title="手动控制Future"></a>手动控制Future</h3><p>1、<code>complete</code> - 手动设置结果。强制完成任务并设置结果。</p>
<pre><code class="java">// 超时手动完成任务
CompletableFuture&lt;String&gt; future = new CompletableFuture&lt;&gt;();

// 模拟超时控制
new Thread(() -&gt; {
    try {
        Thread.sleep(2000);
        future.complete(&quot;Fallback Data&quot;);
    } catch (InterruptedException e) {
        future.completeExceptionally(e);
    }
}).start();

System.out.println(future.get()); // &quot;Fallback Data&quot;（如果超时）
</code></pre>
<p>2、<code>completeExceptionally</code> - 手动设置异常。强制任务失败并抛出异常。</p>
<pre><code class="java">// 任务验证失败时主动终止
CompletableFuture&lt;String&gt; future = new CompletableFuture&lt;&gt;();

if (invalidInput) {
    future.completeExceptionally(new IllegalArgumentException(&quot;Invalid input&quot;));
} else {
    future.complete(&quot;Valid Result&quot;);
}
</code></pre>
<h2 id="对比总结"><a href="#对比总结" class="headerlink" title="对比总结"></a>对比总结</h2><table>
<thead>
<tr>
<th style="text-align:left">类</th>
<th style="text-align:left">核心场景</th>
<th style="text-align:left">是否支持链式调用</th>
<th style="text-align:left">任务类型</th>
<th style="text-align:left">底层机制</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left"><code>FutureTask</code></td>
<td style="text-align:left">手动包装异步任务</td>
<td style="text-align:left">❌</td>
<td style="text-align:left">一次性任务</td>
<td style="text-align:left">线程池或单独线程执行</td>
</tr>
<tr>
<td style="text-align:left"><code>ScheduledFuture</code></td>
<td style="text-align:left">延迟/周期性任务</td>
<td style="text-align:left">❌</td>
<td style="text-align:left">单次或周期性</td>
<td style="text-align:left">基于时间调度</td>
</tr>
<tr>
<td style="text-align:left"><code>ForkJoinTask</code></td>
<td style="text-align:left">分治任务（递归、并行）</td>
<td style="text-align:left">❌</td>
<td style="text-align:left">可分解的子任务</td>
<td style="text-align:left">工作窃取线程池</td>
</tr>
<tr>
<td style="text-align:left"><code>CompletableFuture</code></td>
<td style="text-align:left">异步回调、组合多任务</td>
<td style="text-align:left">✔️</td>
<td style="text-align:left">链式或组合任务</td>
<td style="text-align:left">回调链 + 线程池</td>
</tr>
</tbody>
</table>
<p><strong>如何选择？</strong></p>
<ol>
<li><strong>需要延迟/周期任务</strong> → <code>ScheduledFuture</code></li>
<li><strong>简单异步任务封装</strong> → <code>FutureTask</code></li>
<li><strong>递归或并行计算</strong> → <code>ForkJoinTask</code></li>
<li><strong>复杂异步流程（如回调、组合）</strong> → <code>CompletableFuture</code></li>
</ol>

        </div>
        <!-- .entry-content -->
        <div class="single-reward">
          <div class="reward-open">赏<div class="reward-main">
              <ul class="reward-row">
                <li class="alipay-code"><img src="https://fastly.jsdelivr.net/gh/tiancixiong/cdn@v1.0/img/custom/donate/AliPayQR.jpg"></li>
                <li class="wechat-code"><img src="https://fastly.jsdelivr.net/gh/tiancixiong/cdn@v1.0/img/custom/donate/WeChanQR.png"></li>
              </ul>
            </div>
          </div>
        </div>
        <div style="text-align:center; width: 100%" class="social-share share-mobile" data-disabled="diandian, tencent"></div>
        <footer class="post-footer">
          <div class="post-lincenses"><a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank" rel="nofollow"><i class="fa fa-creative-commons" aria-hidden="true"></i> 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议</a></div>
          <div class="post-tags">
          </div>
          <div class="post-share">
            <div class="social-share sharehidden share-component"></div>
            <i class="iconfont show-share icon-forward"></i>
          </div>
        </footer><!-- .entry-footer -->
      </article>
      <!-- #post-## -->
      <!--<div class="toc" style="background: none;"></div>-->
      <section class="post-squares nextprev">
        
          
            <div class="post-nepre half previous">
          
            <a href="/2024/08/24/红米AX6000刷机记录/" rel="prev">
              <div class="background">
                <img class="lazyload" src="https://fastly.jsdelivr.net/gh/tiancixiong/cdn@v1.0/img/loader/orange.progress-bar-stripe-loader.svg" data-src="https://images.unsplash.com/photo-1460924089785-8467346e18ea?w=540" style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;" onerror="imgError(this,3)" src="https://images.unsplash.com/photo-1460924089785-8467346e18ea?w=540">
              </div>
              <span class="label">
              Previous Post</span>
              <div class="info">
                <h3>
                红米AX6000刷机记录</h3>
                <hr>
              </div>
            </a>
          </div>
        
        
          
            <div class="post-nepre half next">
          
            <a href="/2024/04/03/JUC学习笔记-显式锁：ReentrantLock详解/" rel="next">
              <div class="background">
                <img class="lazyload" src="https://fastly.jsdelivr.net/gh/tiancixiong/cdn@v1.0/img/loader/orange.progress-bar-stripe-loader.svg" data-src="https://images.unsplash.com/photo-1528164344705-47542687000d?w=540" style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;" onerror="imgError(this,3)" src="https://images.unsplash.com/photo-1528164344705-47542687000d?w=540">
              </div>
              <span class="label">
              Next Post</span>
              <div class="info">
                <h3>
                JUC学习笔记-显式锁：ReentrantLock详解</h3>
                <hr>
              </div>
            </a>
          </div>
        
      </section>
      <!-- 评论插件valine -->

<div id="vcomments"></div>
<script>
  window.onload = function(){
      var valine = new Valine();
      valine.init({
        el: '#vcomments',
        appId: "VeenC2gYYyfSOq2rcCSmmruy-MdYXbMMI",
        appKey: "F5kjyHdh4akqc7SDmfzQP8Qi",
		notify: false,
		verify: false,
        path: window.location.pathname,
        placeholder: "你是我一生只会遇见一次的惊喜 ...",
		avatar: "monsterid",
		//meta: [nick,mail,link],
		visitor: true,
        recordIP: "true",
		pageSize: "5" || 10,
		serverURLs: "https://VeenC2gY.api.lncldglobal.com"
      });
	//增加以下六行代码去除 power by valine
    var infoEle = document.querySelector('#vcomments .info');
    if (infoEle && infoEle.childNodes && infoEle.childNodes.length > 0){
      infoEle.childNodes.forEach(function(item) {
        item.parentNode.removeChild(item);
      });
    }
  }
</script>

      <section class="author-profile">
        <div class="info" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
          <a href="https://blog.xiongtianci.com" class="profile gravatar"><img src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@v1.0/img/custom/avatar.jpg" itemprop="image" alt="木浅" height="70" width="70"></a>
          <div class="meta">
            <span class="title">Author</span>
            <h3 itemprop="name">
            <a href="https://blog.xiongtianci.com" itemprop="url" rel="author">木浅</a>
            </h3>
          </div>
        </div>
        <hr>
        <p><i class="iconfont icon-write"></i>YOLO</p>
      </section>
    </main><!-- #main -->
  </div><!-- #primary -->
</div>


    </div>    
    <div class="ins-search">
    <div class="ins-search-mask"></div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <input type="text" class="ins-search-input" placeholder="Type something..."/>
            <span class="ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: 'Posts',
            // PAGES: 'Pages',
            CATEGORIES: 'Categories',
            TAGS: 'Tags',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
    <!-- <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2025 天赐<br>
      powered_by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer> -->
<footer id="colophon" class="site-footer" role="contentinfo">
	<div class="site-info">
		<div class="footertext">
			<div class="img-preload">
				<img src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@1.0/img/other/wordpress-rotating-ball-o.svg">
				<img src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@1.0/img/other/disqus-preloader.svg">
			</div>
			<p class="foo-logo"
				style="background-image: url('https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/img/custom/sakura.svg');">
			</p>
			<div
				style="background-image:linear-gradient(90deg,#6dba82 0,#07b39b 15%,#1098ad 30%,#5073b8 44%,#a166ab 58%,#ef4e7b 72%,#f37055 86%,#f79533 100%);background-size:cover;-webkit-background-clip:text;-webkit-text-fill-color:transparent;user-select:none;margin-top:0.7em;">
				<i>Tip: 本站电脑访问体验更佳耶&nbsp;<i class="fa fa-angellist" style="display:inline"></i></i>
			</div>
			<!-- color: #666666; -->
			<div style="color: #b9b9b9;">&copy;
				2018-2025&nbsp;天赐&nbsp;
			</div>
		</div>
		<!-- 访客统计 -->
		<!--<div id="busuanzi_container"></div>-->
		<!-- 已运行的时间-容器 -->
		<div id="days"></div>
		<div class="footer-device">
			<p id="footer-sponsor">
				<!-- <a href="https://pages.github.com/" target="_blank" alt="GitHub Pages" rel="nofollow"><img
						src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@1.0/img/logo/GitHub.svg" alt="GitHub Pages"
						style="height: 2em; max-height: 2em;" title=""></a>&nbsp;&nbsp;&nbsp; -->
				<!-- <a href="https://coding.net/pages" target="_blank" alt="Coding Pages" rel="nofollow"><img
						src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@1.0/img/logo/Coding.png" alt="Coding Pages"
						style="height: 1.3em; max-height: 1.3em;padding-bottom: 0px;margin-bottom: 0.35em;"
						title=""></a>&nbsp;&nbsp;&nbsp; -->
				<a href="https://www.jsdelivr.com/" target="_blank" alt="Free CDN" rel="nofollow"><img
						src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/img/logo/JsDelivr_Logo.svg" alt="jsDelivr"
						style="height: 2em; max-height: 2em;padding-bottom: 0px;"></a>&nbsp;&nbsp;&nbsp;<a
					href="https://www.google.com/intl/ja/analytics/" target="_blank" alt="Analytics solution"
					rel="nofollow"><img src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/img/logo/Google.svg"
						alt="Google Analytics" style="height: 1.7em; max-height: 1.7em;padding-bottom: 0px;"></a>
			</p>
		</div>
	</div>
	<!-- .site-info -->
</footer>

<!-- <script src="/js/tocbot.js"></script> -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/js/lib.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/js/vendor/clipboard.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/js/InsightSearch.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/js/jquery.fancybox.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/js/zoom.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/js/sakura-app.js"></script>
<!--浏览器搞笑标题-->
<!--<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/js/title_change.js"></script>-->
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/js/volantis.min.js"></script>
<!-- Valine -->
<!--<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>-->
<script src='//unpkg.com/valine/dist/Valine.min.js'></script>
<!--<script src='//unpkg.com/valine@1.3.4/dist/Valine.min.js'></script>-->
<!--<script src="//unpkg.com/valine@1.3.7/dist/Valine.min.js"></script>-->
<!-- 不蒜子 网页计数器 -->
<script src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.min.js"></script> -->
<script type="text/javascript">
	/* <![CDATA[ */
	if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
		var Poi = {
			"pjax": "1",
			"movies": {
				"url": "https://cdn.jsdelivr.net/gh/tiancixiong/cdn@v3.0",
				"name": "/video/Unbroken.mp4",
				"live": "close"
			},
			"windowheight": "fixed",
			"codelamp": "close",
			"ajaxurl": "",
			"order": "asc",
			"formpostion": "bottom"
		};
	} else {
		var Poi = {
			"pjax": "1",
			"movies": {
				"url": "https://cdn.jsdelivr.net/gh/tiancixiong/cdn@v3.0",
				"name": "/video/Unbroken.mp4",
				"live": "open"
			},
			"windowheight": "auto",
			"codelamp": "close",
			"ajaxurl": "",
			"order": "asc",
			"formpostion": "bottom"
		};
	}
		/* ]]> */
</script>
<script>
	$(document).ready(function () {
		if ($(".toc").length > 0 && document.body.clientWidth > 1200) {
			if ($(".pattern-center").length > 0) { //有图的情况
				tocbot.init({
					// Where to render the table of contents.
					tocSelector: '.toc', // 放置目录的容器
					// Where to grab the headings to build the table of contents.
					contentSelector: '.entry-content', // 正文内容所在
					// Which headings to grab inside of the contentSelector element.
					scrollSmooth: true,
					headingSelector: 'h1, h2, h3, h4, h5', // 需要索引的标题级别
					headingsOffset: -400,
					scrollSmoothOffset: -85
				});
			} else {
				tocbot.init({
					// Where to render the table of contents.
					tocSelector: '.toc', // 放置目录的容器
					// Where to grab the headings to build the table of contents.
					contentSelector: '.entry-content', // 正文内容所在
					// Which headings to grab inside of the contentSelector element.
					scrollSmooth: true,
					headingSelector: 'h1, h2, h3, h4, h5', // 需要索引的标题级别
					headingsOffset: -85,
					scrollSmoothOffset: -85
				});
			}
			var offsetTop = $('.toc').offset().top - 95;
			window.onscroll = function () {
				var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
				if (scrollTop >= offsetTop) {
					$('.toc').addClass('toc-fixed');
				} else {
					$('.toc').removeClass('toc-fixed');
				}
			}
		}
	});
</script>
<!-- 已运行的时间-js -->
<script>
	function show_date_time() {
		window.setTimeout("show_date_time()", 1000);
		// 获得建站时间
		var time = "28/11/2018 15:36:06";
		time = time.replace(/\//g, ':').replace(' ', ':');
		time = time.split(':');
		BirthDay = new Date(time[2], (time[1] - 1), time[0], time[3], time[4], time[5]);

		today = new Date();
		timeold = (today.getTime() - BirthDay.getTime());
		sectimeold = timeold / 1000
		secondsold = Math.floor(sectimeold);
		msPerDay = 24 * 60 * 60 * 1000
		msPerYear = 365 * 24 * 60 * 60 * 1000
		e_yearsold = timeold / msPerYear
		yearsold = Math.floor(e_yearsold);
		//e_daysold = timeold / msPerDay
		e_daysold = timeold/msPerDay - yearsold*365;
		daysold = Math.floor(e_daysold);
		e_hrsold = (e_daysold - daysold) * 24;
		hrsold = setzero(Math.floor(e_hrsold));
		e_minsold = (e_hrsold - hrsold) * 60;
		minsold = setzero(Math.floor((e_hrsold - hrsold) * 60));
		seconds = setzero(Math.floor((e_minsold - minsold) * 60));
		document.getElementById('days').innerHTML = "已在风雨中运行 " + yearsold + " 年 " + daysold + " 天 " + hrsold + " 小时 " + minsold + " 分 " + seconds + " 秒";
	}

	function setzero(i) {
		if (i < 10) {
			i = "0" + i
		};
		return i;
	}
	show_date_time();
</script>
<!-- 访客统计-js -->
<!--<script>
		if(true){
			document.getElementById('busuanzi_container').innerHTML="<span id=\"busuanzi_container_site_pv\">本站总访问量 <span id=\"busuanzi_value_site_pv\"></span> 次</span><span class=\"post-meta-divider\"> | </span><span id=\"busuanzi_container_site_uv\">本站访客数 <span id=\"busuanzi_value_site_uv\"></span> 人</span>";
		}else{
			document.getElementById('busuanzi_container').hidden;
		}
	</script>-->
<!-- 百度统计自动推送 -->
<!--<script>
	(function(){
		var bp = document.createElement('script');
		var curProtocol = window.location.protocol.split(':')[0];
		if (curProtocol === 'https') {
			bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
		}
		else {
			bp.src = 'http://push.zhanzhang.baidu.com/push.js';
		}
		var scriptList = document.getElementsByTagName("script");
		var s = scriptList[0];
		s.parentNode.insertBefore(bp, s);
	})();
	</script>
	-->
    <div class="openNav no-select" style="height: 50px;">
      <div class="iconflat no-select" style="width: 50px; height: 50px;">
        <div class="icon"></div>
      </div>
      <div class="site-branding search-form-submit">
        <i class="iconfont js-toggle-search iconsearch icon-search"></i>
      </div>
    </div>
  </section>
  
  <!-- 实现换肤功能 -->
  <div class="skin-menu no-select" id="mainskin"  style="position: fixed">
    <div class="theme-controls row-container">
        <ul class="menu-list">
            <li id="white-bg"><i class="fa fa-television" aria-hidden="true"></i></li>
            <li id="sakura-bg"> <i class="iconfont icon-sakura"></i></li>
            <li id="gribs-bg"> <i class="fa fa-slack" aria-hidden="true"></i></li>
            <li id="KAdots-bg"> <i class="iconfont icon-dots"></i></li>
            <li id="totem-bg"> <i class="fa fa-optin-monster" aria-hidden="true"></i></li>
            <li id="pixiv-bg"> <i class="iconfont icon-pixiv"></i></li>
            <li id="bing-bg"> <i class="iconfont icon-bing"></i></li>
            <li id="dark-bg"> <i class="fa fa-moon-o" aria-hidden="true"></i></li>
        </ul>
    </div>
</div>

<canvas id="night-mode-cover"></canvas>
<style>
#mainskin{
    position: fixed;
}
</style> 
  <div class="changeSkin-gear no-select">
    <div class="keys" id="setbtn"> <span id="open-skinMenu"> 切换主题 | SCHEME TOOL &nbsp;
	<i class="iconfont icon-gear inline-block rotating"></i> </span></div>
</div>
  
  <div id="mo-nav" class="">
  <div class="m-avatar">
    <img src="https://fastly.jsdelivr.net/gh/tiancixiong/cdn@v1.0/img/custom/avatar.jpg">
  </div>
  <p style="text-align: center; color: #333; font-weight: 900; font-family: 'Ubuntu', sans-serif; letter-spacing: 1.5px">天赐の小站</p>
  <p style="text-align: center; word-spacing: 20px;">
    
  </p>
  <ul id="menu-new-1" class="menu">
    
      <li>
        <a href="/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-fort-awesome faa-horizontal" aria-hidden="true"></i>
            首页
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="/archives">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-terminal faa-vertical" aria-hidden="true"></i>
            极客
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/categories/技术/">
                  <i class="fa fa-code" aria-hidden="true"></i>
                  技术
                </a>
              </li>
            
              <li>
                <a href="/categories/Linux/">
                  <i class="fa fa-linux" aria-hidden="true"></i>
                  Linux
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="/archives">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-slack faa-spin" aria-hidden="true"></i>
            爱好
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/categories/电影/">
                  <i class="fa fa-film" aria-hidden="true"></i>
                  电影
                </a>
              </li>
            
              <li>
                <a href="/categories/日语/">
                  <i class="fa fa-language" aria-hidden="true"></i>
                  日语
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="/archives">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-archive faa-ring" aria-hidden="true"></i>
            归档
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/categories/生活/">
                  <i class="fa fa-file-text-o" aria-hidden="true"></i>
                  生活
                </a>
              </li>
            
              <li>
                <a href="/categories/随想/">
                  <i class="fa fa-commenting-o" aria-hidden="true"></i>
                  随想
                </a>
              </li>
            
              <li>
                <a href="/categories/资源/">
                  <i class="fa fa-cloud-download" aria-hidden="true"></i>
                  资源
                </a>
              </li>
            
              <li>
                <a href="/categories/转载/">
                  <i class="fa fa-book" aria-hidden="true"></i>
                  转载
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="/comment/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-pencil-square-o faa-tada" aria-hidden="true"></i>
            留言板
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="/links/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-link faa-shake" aria-hidden="true"></i>
            友人帐
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="/donate/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-heart faa-burst" aria-hidden="true"></i>
            赞赏
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-leaf faa-falling" aria-hidden="true"></i>
            关于
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/about/">
                  <i class="fa fa-meetup" aria-hidden="true"></i>
                  我？
                </a>
              </li>
            
              <li>
                <a href="/theme-sakura/">
                  <i class="fa iconfont icon-sakura" aria-hidden="true"></i>
                  主题
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="/atom.xml">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-rss faa-passing" aria-hidden="true"></i>
            RSS
          </span>
        </a>
        
      </li>
    
  </ul>
  <p style="text-align: center; font-size: 13px; color: #b9b9b9;">&copy 2019 hexo-sakura</p>
</div>
<button onclick="topFunction()" class="mobile-cd-top" id="moblieGoTop" title="Go to top" style="display: none;"><i class="fa fa-chevron-up" aria-hidden="true"></i></button>
  <!--<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer@1.10.1/dist/APlayer.min.css">-->
<!--<script src="https://cdn.jsdelivr.net/npm/aplayer@1.10.1/dist/APlayer.min.js"></script>-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/css/aplayer/APlayer.min.css">
<script src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/js/aplayer/APlayer.min.js"></script>

<style>
  .aplayer .aplayer-lrc {
    height: 35px;
  }
  .aplayer .aplayer-lrc p{
    font-size: 16px;
    font-weight: 700;
    line-height: 18px !important;
  }
  .aplayer .aplayer-lrc p.aplayer-lrc-current{
    color: #FF1493;
  }
  /*.aplayer.aplayer-narrow .aplayer-body{
    left: -66px !important;
  }*/
  .aplayer.aplayer-fixed .aplayer-lrc {
    display: none;
  }
  .aplayer .aplayer-lrc.aplayer-lrc-hide {
      display:none !important;
  }
  .aplayer.aplayer-fixed .lrc-show {
    display: block;
    background: rgba(255, 255, 255, 0.8);
  }
</style>
<div class="aplayer"

    data-id="7040682880"

    data-server="tencent"

    data-type="playlist"

    data-fixed="true"

    data-autoplay="false"

    data-loop="all"

    data-order="random"

    data-preload="auto"

    data-volume="0.5"

    data-mutex="true"

    data-listFolded="false"

</div>
<!-- Meting 一个支持各种音乐平台(腾讯、网易...)的音乐 API 框架 -->
<!--<script src="https://cdn.jsdelivr.net/npm/meting@2.0.1/dist/Meting.min.js"></script>-->
<script src="https://cdn.jsdelivr.net/gh/tiancixiong/cdn@sakura-theme/js/aplayer/Meting.min.js"></script>
<script>
  $(function(){
    $('body').on('click', '.aplayer', function(){
      if($('.aplayer-button').hasClass('aplayer-play')) {
        $('.aplayer-lrc').removeClass('lrc-show');
      } else {
        $('.aplayer-lrc').addClass('lrc-show');
      }
    })
  });
</script>
</body>
</html>